package services

import (
	"fmt"
	global2 "longmen/server/config/global"
	"longmen/server/internal/services/nami/utils"
	"longmen/server/pkg/common/api_models"
	_const "longmen/server/pkg/common/helper/const"
	string2 "longmen/server/pkg/common/helper/string"
	time2 "longmen/server/pkg/common/helper/timehelper"
	utils2 "longmen/server/pkg/common/helper/util"
	"longmen/server/pkg/db/mysql/db_main"
	"longmen/server/pkg/db/mysql/models/models_main"
	"longmen/server/pkg/db/redis/cache"
	"sort"
	"time"

	"github.com/jinzhu/copier"
	"gorm.io/gorm"
)

/**
 * @author Jared
 * @description 获取抽奖活动信息, 判断当前是否存在抽奖活动
 * @createTime 10:08 2022/10/19
 **/
func (s *Service) GetLottery(uid int) (*api_models.GetLotteryResp, error) {
	list, err := db_main.GetEffectiveLotteryList()
	if err != nil {
		return nil, err
	}

	joinTypeMp := map[int]int{}
	joinTypeMp[models_main.JOIN_USER_TYPE_ALL] = 1
	joinTypeMp[models_main.JOIN_USER_TYPE_COMMON] = 1
	if uid > 0 {
		noble, err := db_main.GetNobleById(uint8(uid))
		if err != nil {
			return nil, err
		}
		if noble.Id > 0 {
			joinTypeMp[models_main.JOIN_USER_TYPE_NOBLE] = 1
		}
	}

	if len(joinTypeMp) > 0 {
		var nList []models_main.Lottery
		for k, v := range list {
			_, ok := joinTypeMp[v.JoinUserType]
			if ok {
				nList = append(nList, list[k])
			}
		}
		list = nList
	}

	if len(list) > 0 {
		sort.Slice(list, func(i, j int) bool {
			return list[i].Id > list[j].Id
		})
		return &api_models.GetLotteryResp{
			IsLottExists: true,
			LottId:       list[0].Id,
			AppBgPic:     list[0].AppBgPic,
			PcBgPic:      list[0].PcBgPic,
			Name:         list[0].Name,
			RuleDesc:     list[0].RuleDesc,
		}, nil
	}
	return &api_models.GetLotteryResp{
		IsLottExists: false,
	}, nil
}

/**
 * @author Jared
 * @description 获取中奖弹幕信息
 * @createTime 10:08 2022/10/19
 **/
func (s *Service) GetAwardBullets() ([]string, error) {
	history, err := db_main.GetUserLotteryHistoryParam(nil, 1, 30)
	if err != nil {
		return nil, err
	}

	var awardIds []int
	var lottIds []int
	var uids []int
	for _, v := range history {
		awardIds = append(awardIds, v.LotteryAwardId)
		lottIds = append(lottIds, v.LotteryId)
		found := false
		for _, uid := range uids {
			if v.Uid == uid {
				found = true
				break
			}
		}
		if !found {
			uids = append(uids, v.Uid)
		}
	}
	awardIds = utils2.DeduplicationSlice(awardIds)
	lottIds = utils2.DeduplicationSlice(lottIds)

	awards, err := db_main.GetLotteryAwardsByIds(awardIds)
	if err != nil {
		return nil, err
	}
	awardMp := map[int]models_main.LotteryAward{}
	for k, v := range awards {
		awardMp[v.Id] = awards[k]
	}

	awardCfgs, err := db_main.GetLotteryAwardConfigsByLottIds(lottIds)
	if err != nil {
		return nil, err
	}
	cfgMp := map[int]models_main.LotteryAwardConfig{}
	for k, v := range awardCfgs {
		_, ok := awardMp[v.LotteryAwardId]
		if ok {
			cfgMp[v.LotteryAwardId] = awardCfgs[k]
		}
	}

	users, err := db_main.GetUsersParam(map[string]interface{}{"id": map[string]interface{}{"in": uids}}, "", 0, 0)
	if err != nil {
		return nil, err
	}
	userMp := map[int]*models_main.User{}
	for k, v := range users {
		userMp[v.Id] = users[k]
	}

	var bullets []string
	for _, v := range history {
		award, ok := awardMp[v.LotteryAwardId]
		cfg, ok2 := cfgMp[v.LotteryAwardId]
		user, ok3 := userMp[v.Uid]
		if ok && ok2 && ok3 {
			bullets = append(bullets, fmt.Sprintf(
				"恭喜 %s 抽中 %sx%d",
				user.NickName,
				award.Name,
				cfg.LottNum))
		}
	}
	return bullets, nil
}

/**
 * @author Jared
 * @description 获取抽奖奖品信息
 * @createTime 10:09 2022/10/19
 **/
func (s *Service) GetLotteryAwardsInfo(uid, lottId int) (*api_models.LotteryAwardsInfoResp, error) {
	lott, err := db_main.GetLotteryById(lottId)
	if err != nil {
		return nil, err
	}
	if lott == nil {
		return nil, fmt.Errorf("暂无抽奖活动")
	}

	awardCfgs, err := db_main.GetLotteryAwardConfigsByLottId(lottId)
	if err != nil {
		return nil, err
	}

	var awardIds []int
	for _, v := range awardCfgs {
		awardIds = append(awardIds, v.LotteryAwardId)
	}
	awardIds = utils2.DeduplicationSlice(awardIds)

	awards, err := db_main.GetLotteryAwardsByIds(awardIds)
	if err != nil {
		return nil, err
	}
	awardMp := map[int]models_main.LotteryAward{}
	for k, v := range awards {
		awardMp[v.Id] = awards[k]
	}

	var awardList []api_models.LotteryAward
	for _, v := range awardCfgs {
		award, ok := awardMp[v.LotteryAwardId]
		if ok {
			awardList = append(awardList, api_models.LotteryAward{
				Id:         award.Id,
				Name:       award.Name,
				AwardPic:   award.AwardPic,
				LottNum:    v.LottNum,
				SurplusNum: award.StockNum - award.UsedNum,
				Unit:       award.Unit,
			})
		}
	}

	var checkin = &models_main.UserCheckin{}
	if uid > 0 {
		checkin, err = db_main.GetUserCheckInByUid(uid)
		if err != nil {
			return nil, err
		}
		if checkin == nil {
			checkin = &models_main.UserCheckin{
				Uid:    uid,
				OrdNum: 1,
			}
			err = db_main.InsertUserCheckin(checkin)
			if err != nil {
				return nil, err
			}
		}
	}

	if len(awardList) > 10 {
		awardList = awardList[:10]
	}
	return &api_models.LotteryAwardsInfoResp{
		AwardList:     awardList,
		GoldCost:      lott.GoldCost,
		DiamondCost:   lott.DiamondCost,
		FreeDrawTimes: checkin.DrawNum,
	}, nil
}

/**
 * @author Jared
 * @description 抽奖返回抽奖结果
 * @createTime 9:15 2022/10/20
 **/
func (s *Service) DrawLottery(user *models_main.User, req api_models.DrawLotteryReq) (*api_models.DrawLotteryResp, error) {
	lott, err := db_main.GetLotteryById(req.LottId)
	if err != nil {
		return nil, err
	}
	if lott == nil {
		return nil, fmt.Errorf("暂无抽奖活动")
	}

	var coinType = 0
	var drawCost = 0
	var checkin *models_main.UserCheckin
	switch _const.FundsType(req.DrawType) {
	case _const.CoinGold: //钻石抽奖
		if user.Gold < lott.GoldCost {
			return &api_models.DrawLotteryResp{
				IsSucceed: false,
				FailTips:  "您的余额不足, 无法参与抽奖",
			}, nil
		}
		drawCost = lott.GoldCost
		coinType = int(_const.CoinGold)
	case _const.CoinDiamond: //宝石抽奖
		if user.Diamond < lott.DiamondCost {
			return &api_models.DrawLotteryResp{
				IsSucceed: false,
				FailTips:  "您的余额不足, 无法参与抽奖",
			}, nil
		}
		drawCost = lott.DiamondCost
		coinType = int(_const.CoinDiamond)
	default: //免费条件抽奖
		checkin, err = db_main.GetUserCheckInByUid(user.Id)
		if err != nil {
			return nil, err
		}
		if checkin == nil {
			return nil, fmt.Errorf("您还没有免费抽奖次数, 快去做任务吧~")
		}
		if checkin.DrawNum <= 0 {
			return &api_models.DrawLotteryResp{
				IsSucceed: false,
				FailTips:  "您还没有免费抽奖次数, 快去做奖励任务吧~",
			}, nil
		}
	}

	awardConfigMap := make(map[int]models_main.LotteryAwardConfig)
	awardSlice := []models_main.LotteryAward{}

	awardCfgs, err := db_main.GetLotteryAwardConfigsByLottId(req.LottId)

	if err != nil {
		return nil, err
	}
	var awardIds []int
	for _, v := range awardCfgs {
		awardIds = append(awardIds, v.LotteryAwardId)
		awardConfigMap[v.LotteryAwardId] = v
	}
	awardIds = utils2.DeduplicationSlice(awardIds)
	awards, err := db_main.GetLotteryAwardsByIds(awardIds)
	if err != nil {
		return nil, err
	}

	for _, v := range awards {
		awardSlice = append(awardSlice, v)
	}

	shotAwardCfg, shotAward, err := s.DoDrawFunc(awardConfigMap, awardSlice)
	if err != nil {
		return &api_models.DrawLotteryResp{
			IsSucceed: false,
			FailTips:  err.Error(),
		}, nil
	}

	userProfit := &models_main.UserProfit{
		Uid:         user.Id, //记录的主人
		FUid:        0,       //system
		ConsumeType: _const.CONSUME_LOTTERY_DRAW,
		Type:        _const.TYPE_CONSUME, //这是一个消费记录
		CoinCount:   drawCost,
		Content:     lott.Name,
		Resid:       lott.Id,
		Count:       shotAwardCfg.LottNum,
		CreateTime:  time.Now(),
		CoinType:    coinType,
		OrderNo:     utils2.GenOrderId("GL", 1),
		Liveid:      0,
	}
	lottHistory := &models_main.UserLotteryHistory{
		Uid:            user.Id,
		LotteryId:      lott.Id,
		LotteryAwardId: shotAwardCfg.LotteryAwardId,
		AwardType:      shotAward.AwardType,
		LottNum:        shotAwardCfg.LottNum,
		DrawTime:       time.Now(),
	}

	err = global2.GetX().Transaction(func(tx *gorm.DB) error {
		err = db_main.InsertUserLotteryHistoryByTransactions(tx, lottHistory)
		if err != nil {
			return err
		}

		if _const.FundsType(req.DrawType) == _const.CoinGold ||
			_const.FundsType(req.DrawType) == _const.CoinDiamond {
			//克拉抽奖 鹰钻抽奖
			_, _, err = db_main.UpdateAmountByTx(
				user.Id,
				-drawCost,
				_const.FundsType(req.DrawType),
				tx,
				_const.WALLET_BALANCE_HIDE,
				[]*models_main.UserProfit{userProfit},
			)
			if err != nil {
				return err
			}
		} else {
			//条件抽奖
			checkin.DrawNum -= 1
			return db_main.UpdateUserCheckinByTransactions(tx, []string{"draw_num"}, checkin)
		}
		return nil
	})
	if err != nil {
		return nil, err
	}
	//后续操作
	utils.SafeGo(func() {
		s.AfterLotteryWork(AwardUnionInfo{
			Lott:    lott,
			User:    user,
			Config:  shotAwardCfg,
			Award:   shotAward,
			History: lottHistory,
		})
	})
	cache.DelUserFullCache(user.Id)
	return &api_models.DrawLotteryResp{
		IsSucceed: true,
		AwardId:   shotAward.Id,
		Name:      shotAward.Name,
		AwardPic:  shotAward.AwardPic,
		LottNum:   shotAwardCfg.LottNum,
		Unit:      shotAward.Unit,
	}, nil
}

type AwardUnionInfo struct {
	Lott    *models_main.Lottery
	User    *models_main.User
	Config  *models_main.LotteryAwardConfig
	Award   *models_main.LotteryAward
	History *models_main.UserLotteryHistory
}

/**
 * @author Jared
 * @description 抽奖后处理
 * @createTime 13:45 2022/10/21
 **/
func (s *Service) AfterLotteryWork(info AwardUnionInfo) {
	defer func() {
		if err := recover(); err != nil {
			global2.Log.Error(err)
		}
	}()
	//扣减库存
	s.DecreaseAwardStock(info)
	//虚拟物品发放
	s.VirtualAwardGive(info)
	//通知用户
	s.NotifyUser(info)
}

const (
	AwardVirtualTypeExp       = iota //经验
	AwardVirtualTypeGold             //鹰钻
	AwardVirtualTypeDiamond          //克拉
	AwardVirtualTypeGift             //礼物
	AwardVirtualTypeProps            //道具
	AwardVirtualTypeNobleExpr        //贵族体验天数
	AwardVirtualTypeFreeDraw         //免费抽奖次数
)

/**
 * @author Jared
 * @description 虚拟物品发放
 * @createTime 13:46 2022/10/21
 **/
func (s *Service) VirtualAwardGive(info AwardUnionInfo) {
	if info.Award.AwardType != models_main.LOTTERY_AWARD_TYPE_VIRTUAL {
		return
	}

	info.History.GiveTime = time.Now()
	info.History.GiveStatus = models_main.LOTTERY_AWARD_GIVE_COMPLETE

	switch _const.RewardType(info.Award.VirtualType) {
	case AwardVirtualTypeExp:
		processExp(info)
	case AwardVirtualTypeGold:
		processCoin(int(_const.CoinGold), info)
	case AwardVirtualTypeDiamond:
		processCoin(int(_const.CoinDiamond), info)
	case AwardVirtualTypeGift:
		processGift(info)
	case AwardVirtualTypeProps:
		processProps(info)
	case AwardVirtualTypeNobleExpr:
		processNobleExpr(info)
	case AwardVirtualTypeFreeDraw:
		processFreeDraw(info)
	default:
		global2.Log.Errorf("暂无此类型虚拟物品 awardId:%d", info.Award.Id)
		return
	}
}

func processExp(info AwardUnionInfo) {
	info.User.Point += info.Config.LottNum
	err := global2.GetX().Transaction(func(tx *gorm.DB) error {
		err := db_main.IncreaseUser(
			tx,
			info.Config.LottNum, "point",
			info.User.Id, "id")
		if err != nil {
			return err
		}
		return db_main.UpdateUserLotteryHistoryByTransactions(
			tx,
			[]string{"give_time", "give_status"},
			info.History,
		)
	})
	if err != nil {
		global2.Log.Error(err)
		return
	}
}

func processCoin(coinType int, info AwardUnionInfo) {
	userProfit := &models_main.UserProfit{
		Uid:         info.User.Id,
		CoinCount:   info.Config.LottNum * 100,
		Content:     info.Lott.Name,
		Resid:       info.Award.Id,
		Count:       info.Config.LottNum * 100,
		CreateTime:  time.Now(),
		CoinType:    coinType,
		ConsumeType: _const.PROFIT_LOTTERY_AWARD,
		Type:        _const.TYPE_PROFIT,
		OrderNo:     utils2.GenOrderId("GL", 1),
		Liveid:      0,
	}
	err := global2.GetX().Transaction(func(tx *gorm.DB) error {
		//抽奖虚拟物品奖励
		_, _, err := db_main.UpdateAmountByTx(
			info.User.Id,
			info.Config.LottNum*100,
			_const.FundsType(coinType),
			tx,
			_const.WALLET_BALANCE_HIDE,
			[]*models_main.UserProfit{userProfit},
		)
		if err != nil {
			return err
		}
		return db_main.UpdateUserLotteryHistoryByTransactions(
			tx,
			[]string{"give_time", "give_status"},
			info.History,
		)
	})
	if err != nil {
		global2.Log.Error(err)
		return
	}
}

func GetMyNoble(uid int) (*api_models.GetNobleByIdResp, error) {
	record, err := db_main.GetNobleRecordByUid(uid)
	if err != nil {
		return nil, err
	}
	resp := &api_models.GetNobleByIdResp{}
	if record.Id > 0 {
		resp.Expiration = int64(time2.GetLeftDays(record.Expiration))
		nobleInfo, err := cache.GetNoble(record.NobleId)

		if err != nil {
			return resp, err
		}
		resp.From = record.From
		resp.AnchorID = int64(record.AnchorId)
		err = copier.Copy(resp, nobleInfo)
		if err != nil {
			return nil, err
		}
	}
	return resp, nil
}

func processGift(info AwardUnionInfo) {
	gift, err := db_main.GetGiftParam(map[string]interface{}{"id": info.Award.GiftId})
	if err != nil {
		global2.Log.Error(err)
		return
	}
	if gift.Id <= 0 {
		global2.Log.Errorf("抽奖奖品不存在, awardId:%d,giftId:%d", info.Award.Id, info.Award.GiftId)
		return
	}
	if gift.Type != 2 { //活动礼品
		global2.Log.Errorf("非活动礼品不可参与抽奖, awardId:%d,giftId:%d", info.Award.Id, info.Award.GiftId)
		return
	}
	noble, err := GetMyNoble(info.User.Id)
	if err != nil {
		global2.Log.Error(err)
		return
	}
	err = global2.GetX().Transaction(func(tx *gorm.DB) error {
		err = db_main.SaveUserItem(
			tx, noble.Id, info.User.Id, gift.Id,
			2, info.Config.LottNum, gift.Title,
			gift.Title, 999*24*60*60)
		if err != nil {
			return err
		}
		return db_main.UpdateUserLotteryHistoryByTransactions(
			tx,
			[]string{"give_time", "give_status"},
			info.History,
		)
	})
	if err != nil {
		global2.Log.Error(err)
		return
	}
}

func processProps(info AwardUnionInfo) {
	noble, err := GetMyNoble(info.User.Id)
	if err != nil {
		global2.Log.Error(err)
		return
	}
	props, err := db_main.GetPropsINFO(info.Award.PropsId)
	if err != nil {
		global2.Log.Error(err)
		return
	}
	err = global2.GetX().Transaction(func(tx *gorm.DB) error {
		err = db_main.SaveUserItem(
			tx, noble.Id, info.User.Id, props.Id,
			props.Type, info.Config.LottNum, props.Name,
			props.Remark, 999*24*60*60)
		if err != nil {
			return err
		}
		return db_main.UpdateUserLotteryHistoryByTransactions(
			tx,
			[]string{"give_time", "give_status"},
			info.History,
		)
	})
	if err != nil {
		global2.Log.Error(err)
		return
	}
}

func processNobleExpr(info AwardUnionInfo) {
	var (
		err       error
		vipLen    = 0
		expTime   = time.Now().Unix() + int64(info.Config.LottNum)*24*3600 - 1
		noble     *models_main.NobleNew
		nobleList []*models_main.NobleNew
		from      = 2
	)

	nr, err := GetMyNoble(info.User.Id)
	if err != nil {
		global2.Log.Error(err)
		return
	}

	// 1.获取等级列表
	nobleList, err = db_main.GetNobleList()
	if vipLen = len(nobleList); err != nil {
		global2.Log.Error(err)
		return
	}
	if vipLen == 0 {
		global2.Log.Error("系统未配置VIP等级")
		return
	}

	// 2.随机取一个VIP
	idx := string2.RandInt(0, vipLen)
	noble = nobleList[idx]
	if nr.Id > 0 {
		expTime = nr.Expiration*24*3600 + expTime
		noble, _ = db_main.GetNobleById(uint8(nr.Id))
		from = 1
	}
	// noblePrivilege, err := repository.GetNoblePrivilege(noble.Id)
	if err != nil {
		global2.Log.Error("系统未配置VIP等级信息")
		return
	}
	// 3.发放礼物道具
	//坐骑
	mount, err := db_main.GetPropsINFO(int(noble.PropsID))
	if err != nil {
		global2.Log.Error("获取贵族座骑信息失败")
		return
	}
	err = global2.GetX().Transaction(func(tx *gorm.DB) error {
		err = db_main.SaveUserItem(
			tx, int(noble.Id), info.User.Id, mount.Id,
			mount.Type, 1, mount.Name,
			mount.Remark, int64(info.Config.LottNum*24*60*60))
		if err != nil {
			return err
		}

		// 4.写入一条等级关联记录
		if err = db_main.InsertNobleRecordByTx(tx, &models_main.NobleRecord{
			NobleId:    noble.Id,           //贵族ID
			Uid:        uint(info.User.Id), //用户ID
			Expiration: expTime,            //到期时间戳
			AnchorId:   uint(nr.AnchorID),
			From:       from,
			CreateTime: time2.GetTimeStamp(1),
		}); err != nil {
			return err
		}

		return db_main.UpdateUserLotteryHistoryByTransactions(
			tx,
			[]string{"give_time", "give_status"},
			info.History,
		)
	})
	if err != nil {
		global2.Log.Error(err)
		return
	}
	cache.DelUserFullCache(info.User.Id)
}

func processFreeDraw(info AwardUnionInfo) {
	var userCheckin *models_main.UserCheckin
	userCheckin, err := db_main.GetUserCheckInByUid(info.User.Id)
	if err != nil {
		global2.Log.Error(err)
		return
	}

	err = global2.GetX().Transaction(func(tx *gorm.DB) error {
		if userCheckin.Uid == 0 {
			userCheckin = &models_main.UserCheckin{
				Uid:     info.User.Id,
				DrawNum: info.Config.LottNum,
			}
			err = db_main.InsertUserCheckinByTx(tx, userCheckin)
			if err != nil {
				global2.Log.Error(err)
			}
		} else {
			userCheckin.DrawNum += info.Config.LottNum
			err = db_main.UpdateUserCheckinByTransactions(tx, []string{"draw_num"}, userCheckin)
			if err != nil {
				return err
			}
		}
		return db_main.UpdateUserLotteryHistoryByTransactions(
			tx,
			[]string{"give_time", "give_status"},
			info.History,
		)
	})
	if err != nil {
		global2.Log.Error(err)
	}
}

/**
 * @author Jared
 * @description 生成通知消息
 * @createTime 18:27 2022/10/21
 **/
func (s *Service) NotifyUser(info AwardUnionInfo) {
	//然后生成notice通知用户
	notice := models_main.Notice{
		UserId: uint(info.User.Id),
		Content: fmt.Sprintf(
			"恭喜您参与%s，获得奖品如下：%sx%d",
			info.Lott.Name,
			info.Award.Name,
			info.Config.LottNum,
		),
	}
	err := global2.GetX().Transaction(func(tx *gorm.DB) error {
		return db_main.InsertNoticeByTx(tx, &notice)
	})
	if err != nil {
		global2.Log.Error(err)
		return
	}
}

/**
 * @author Jared
 * @description 扣减库存
 * @createTime 11:49 2022/10/21
 **/
func (s *Service) DecreaseAwardStock(info AwardUnionInfo) {
	award, err := db_main.GetLotteryAwardsById(info.Award.Id)
	if err != nil {
		global2.Log.Error(err)
		return
	}

	//经验、金币、钻石 只扣一份库存
	if award.VirtualType < 3 {
		award.UsedNum += 1
	} else {
		award.UsedNum += info.Config.LottNum
	}

	err = db_main.UpdateLotteryAward([]string{"used_num"}, award)
	if err != nil {
		global2.Log.Error(err)
		return
	}
}

/**
 * @author Jared
 * @description 抽奖方法
 * @createTime 10:29 2022/10/21
 **/
func (s *Service) DoDrawFunc(awardCfgs map[int]models_main.LotteryAwardConfig, awards []models_main.LotteryAward) (
	shotAwardCfg *models_main.LotteryAwardConfig,
	shotAward *models_main.LotteryAward,
	err error,
) {
	stock := 0
	var awardSlice []models_main.LotteryAward
	for _, v := range awards {
		if _, ok := awardCfgs[v.Id]; ok {
			v.Weights = v.StockNum - v.UsedNum
			if v.Weights > 0 {
				awardSlice = append(awardSlice, v)
				stock += v.StockNum - v.UsedNum
			}
		}
	}

	if stock <= 0 {
		err = fmt.Errorf("奖品库存不足")
		return
	}

	sort.Slice(awardSlice, func(j, x int) bool {
		if awardSlice[j].Weights < awardSlice[x].Weights {
			return true
		}
		return false
	})
	totalWeights := 0
	for k, v := range awardSlice {
		totalWeights += v.Weights
		awardSlice[k].Weights = totalWeights
	}

	n := utils2.MaxMinRand(1, stock)

	for _, v := range awardSlice {
		if n < v.Weights {
			shotAward = &v
			for _, l := range awardCfgs {
				if l.LotteryAwardId == v.Id {
					shotAwardCfg = &l
					break
				}
			}
			break
		}
	}
	if shotAwardCfg == nil {
		err = fmt.Errorf("奖品配置错误")
	}
	return
}

/**
 * @author Jared
 * @description 获取中奖记录信息
 * @createTime 10:10 2022/10/19
 **/
func (s *Service) GetLotteryHistory(uid int, req *api_models.LotteryHistoryReq) ([]api_models.LotteryHistoryResp, error) {
	if uid <= 0 {
		return []api_models.LotteryHistoryResp{}, nil
	}
	history, err := db_main.GetUserLotteryHistoryParam(map[string]interface{}{"uid": uid}, req.Page, req.Size)
	if err != nil {
		return nil, err
	}

	var awardIds []int
	var lottIds []int
	for _, v := range history {
		awardIds = append(awardIds, v.LotteryAwardId)
		lottIds = append(lottIds, v.LotteryId)
	}
	awardIds = utils2.DeduplicationSlice(awardIds)
	lottIds = utils2.DeduplicationSlice(lottIds)

	awards, err := db_main.GetLotteryAwardsByIds(awardIds)
	if err != nil {
		return nil, err
	}
	awardMp := map[int]models_main.LotteryAward{}
	for k, v := range awards {
		awardMp[v.Id] = awards[k]
	}

	awardCfgs, err := db_main.GetLotteryAwardConfigsByLottIds(lottIds)
	if err != nil {
		return nil, err
	}
	cfgMp := map[int]models_main.LotteryAwardConfig{}
	for k, v := range awardCfgs {
		_, ok := awardMp[v.LotteryAwardId]
		if ok {
			cfgMp[v.LotteryAwardId] = awardCfgs[k]
		}
	}

	var resp []api_models.LotteryHistoryResp
	for _, v := range history {
		var (
			AwardPic       string
			Name           string
			LottNum        int
			DeliveryStatus string
		)
		award, ok := awardMp[v.LotteryAwardId]
		if !ok {
			continue
		}
		AwardPic = award.AwardPic
		Name = award.Name

		cfg, ok := cfgMp[v.LotteryAwardId]
		if !ok {
			continue
		}
		LottNum = cfg.LottNum

		DeliveryStatus = func() string {
			switch award.AwardType {
			case models_main.LOTTERY_AWARD_TYPE_VIRTUAL:
				if v.GiveStatus == models_main.LOTTERY_AWARD_GIVE_PENDING {
					return "待发放"
				}
				if v.GiveStatus == models_main.LOTTERY_AWARD_GIVE_COMPLETE {
					return "已发放"
				}
			case models_main.LOTTERY_AWARD_TYPE_REAL:
				if v.GiveStatus == models_main.LOTTERY_AWARD_GIVE_PENDING {
					return "待发货"
				}
				if v.GiveStatus == models_main.LOTTERY_AWARD_GIVE_COMPLETE {
					return "已发货"
				}
			}
			return "待发放"
		}()

		resp = append(resp, api_models.LotteryHistoryResp{
			Id:             v.Id,
			AwardPic:       AwardPic,
			Name:           Name,
			LottNum:        LottNum,
			GiveTime:       v.DrawTime.Format("01-02 15:04"),
			ExpressNo:      v.ExpressNO,
			GiveStatus:     v.GiveStatus,
			DeliveryStatus: DeliveryStatus,
		})
	}
	return resp, nil
}
